import java.util.HashMap;
import java.util.Map; 
import java.util.List;
import java.util.ArrayList;
/**
 * @author Sam Snyder
 *
 */
public class Undergrad implements Graded {

	private static final Map <LetterGrade, Float> lettertoGPA = new HashMap<LetterGrade, Float>();
	private static final Short MAXCREDITHOURS = 5;
	private List<List<LetterGrade>> transcript = new ArrayList<List<LetterGrade>>();
	private Short lastgrade;
	
	
	static {
		// Associate letter grades with their numerical values
		lettertoGPA.put(LetterGrade.EPURE, 0f);
		lettertoGPA.put(LetterGrade.DPURE, 1f);
		lettertoGPA.put(LetterGrade.DPLUS, 1.3f);
		lettertoGPA.put(LetterGrade.CMINUS, 1.7f);
		lettertoGPA.put(LetterGrade.CPURE, 2f);
		lettertoGPA.put(LetterGrade.CPLUS, 2.3f);
		lettertoGPA.put(LetterGrade.BMINUS, 2.7f);
		lettertoGPA.put(LetterGrade.BPURE, 3f);
		lettertoGPA.put(LetterGrade.BPLUS, 3.3f);
		lettertoGPA.put(LetterGrade.AMINUS, 3.7f);
		lettertoGPA.put(LetterGrade.APURE, 4f);
	}
	
	public Undergrad() {
		
		// Populate with empty lists so that other methods may be certain 
		// of their existence.
		for (int i = 0; i <= MAXCREDITHOURS; i++) {
			List<LetterGrade> gradeList = new ArrayList<LetterGrade>();
			transcript.add(i, gradeList);
		}
	}
	
	/* (non-Javadoc)
	 * @see Graded#assignGrade(short, LetterGrade)
	 */
	@Override
	public void assignGrade(short credits, LetterGrade grade) {
		List<LetterGrade> gradeList = new ArrayList<LetterGrade>();
		gradeList = transcript.get(credits);
		gradeList.add(grade);
		transcript.set(credits, gradeList);
		lastgrade = credits;
	}

	/* (non-Javadoc)
	 * @see Graded#getGPA()
	 */
	@Override
	public float getGPA() {
		float possible = 0;
		float achieved = 0;
		// Iterate through the lists calculating hours attempted & points earned
		for (int i = 1; i <= MAXCREDITHOURS; i++ ) {
			List<LetterGrade> gradeList = transcript.get(i);
			possible += i*gradeList.size();
			// Iterate through each grade of the given number of credit hours
			for (int j = 0; j < gradeList.size(); j++) {
				achieved += i*lettertoGPA.get(gradeList.get(j));
			}	
		}
		return achieved/possible;
	}

	/* (non-Javadoc)
	 * @see Graded#getLastGrade()
	 */
	@Override
	public LetterGrade getLastGrade() {
		List<LetterGrade> gradeList = transcript.get(lastgrade);
		return gradeList.get(gradeList.size()-1);
	}

	/* (non-Javadoc)
	 * @see Graded#getTotalCredits()
	 */
	@Override
	public int getTotalCredits() {
		int possible = 0;
		// Sum lengths of the five credit-hour lists
		for (int i = 1; i <= MAXCREDITHOURS; i++) {
			List<LetterGrade> gradeList = transcript.get(i);
			possible += i*gradeList.size();
		}
		return possible;
	}

}
